package com.googlecode.cswish.struts.hibernate.ehcache;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import net.sf.ehcache.search.Query;
import net.sf.ehcache.search.Result;
import net.sf.ehcache.search.Results;
import net.sf.ehcache.search.attribute.AttributeExtractor;
import net.sf.ehcache.search.expression.BaseCriteria;
import net.sf.ehcache.search.expression.Criteria;

import org.hibernate.cache.spi.CacheKey;

public class InSubCriteria extends BaseCriteria {

	private final String attributeName;
	
	private Criteria subCriteria;
	
	private Set<Object> subSet;
	
	private Ehcache subCache;
	
	public InSubCriteria(String attributeName, Ehcache subCache, Criteria subCriteria) {
		this.attributeName = attributeName;
		this.subCache = subCache;
		this.subCriteria = subCriteria;
	}
	
	@Override
	public boolean execute(Element element,
			Map<String, AttributeExtractor> attributeExtractors) {
		
		if (subSet == null) {
			Query query = subCache.createQuery();
			query.includeKeys();
			query.addCriteria(subCriteria);
			Results results = query.execute();
			
			subSet = new HashSet<Object>(results.size() * 4 / 3);
			for (Result result : results.all()) {
				CacheKey cacheKey = (CacheKey) result.getKey();
				subSet.add(cacheKey.getKey());
			}
		}
		
		if (subSet == null) {
			return false;
		} else {
			Object value = attributeExtractors.get(attributeName).attributeFor(element, attributeName);
			return subSet.contains(value);
		}
	}
}
